import * as SocketIO from 'socket.io';
import { game_event_map } from '../configs_win';
import Crypto from '../utils/crypto';
import TokenMgr from './tokenmgr';
import Roommgr from './roommgr';
import UserMgr from './usermgr';
import { userInfo } from 'os';


let io: SocketIO.Server = null;


function callPathFun(eventName, flag = false){
    let str = flag ? ',发送事件：' : '';
    let path = 'socket_service.ts->监听事件：' + eventName + ',发送事件：';
    return (msg, emitName?) => {
        return path + emitName + '->错误信息：' + msg;
    };
}


export default class Socket_service{

    /**
     * 开启socketio
     */
    static start(config: game_server){
        io = SocketIO(config.CLIENT_PORT);

        io.sockets.on(game_event_map.CONNECTION, (socket) => {

            socket.on(game_event_map.LOGIN, (data: ret & string) => {
                const callPath = callPathFun(game_event_map.LOGIN);
                data = JSON.parse(data);
                
                if(socket.userId){
                    // 已经登录过的忽略
                    return;
                }

                const token = data.token;
                let roomId = data.roomId;
                const time = data.time;
                const sign = data.sign;

                if(token == null || roomId == null || sign == null || time == null){
                    socket.emit(game_event_map.LOGIN_RESULT, {
                        errcode: 1,
                        errmsg: callPath('token == null || roomId == null || sign == null || time == null', game_event_map.LOGIN_RESULT),
                    });
                    return;
                }

                // 检查参数是否被篡改
                const signMd5 = Crypto.md5(roomId + token + time + config.ROOM_PRI_KEY);
                if(signMd5 != sign){
                    socket.emit(game_event_map.LOGIN_RESULT, {
                        errcode: 2,
                        errmsg: callPath('登录失败，sign无效', game_event_map.LOGIN_RESULT),
                    });
                    return;
                }

                // 检查token是否过期
                if(TokenMgr.isTokenValid(token) == false){
                    socket.emit(game_event_map.LOGIN_RESULT, {
                        errcode: 3,
                        errmsg: callPath('token过期', game_event_map.LOGIN_RESULT)
                    });
                    return;
                }

                const userId = TokenMgr.getuserId(token);
                roomId = Roommgr.getUserRoom(userId);
                UserMgr.bind(userId, socket);
                socket.userId = userId;

                // 获取房间玩法信息并初始化数据
                const roomInfo = Roommgr.getRoomInfo(roomId);
                const seatIndex = Roommgr.getUserSeat(userId);
                roomInfo.seats[seatIndex].ip = socket.handshake.address;

                let userData = null;
                let seats: seat[] = [];
                for(let i = 0; i < roomInfo.seats.length; i++){
                    const rs = roomInfo.seats[i];
                    let online = false;
                    if(rs.userId > 0){
                        online = UserMgr.isOnline(rs.userId);
                    }
                    seats.push({
                        userId: rs.userId,
                        ip: rs.ip,
                        score: rs.score,
                        name: rs.name,
                        online: online,
                        ready: rs.ready,
                        seatIndex: i,
                    });
                    if(userId == rs.userId){
                        userData = seats[i];
                    }
                }

                // 通知前端
                const ret: ret = {
                    errcode: 0,
                    errmsg: 'ok',
                    data: {
                        roomId: roomInfo.id,
                        conf: roomInfo.conf,
                        numOfGames: roomInfo.numOfGames,
                        seats: seats,
                    }
                };
                socket.emit(game_event_map.LOGIN_RESULT, ret);

                // 通知其他玩家
                UserMgr.broacastInRoom(game_event_map.NEW_USER_COMES_PUSH, userData, userId);
                socket.gameMgr = roomInfo.gameMgr;

                // 玩家上线，强制设置为true
                socket.gameMgr.setReady(userId);
                socket.emit(game_event_map.LOGIN_FINISHED);

                if(roomInfo.dr != null){
                    const dr = roomInfo.dr;
                    const ramaingTime = (dr.endTime = Date.now()) / 1000;
                    const data = {
                        time: ramaingTime,
                        states: dr.states,
                    };
                    UserMgr.sendMsg(userId, game_event_map.DISSOLVE_NOTICE_PUSH, data);
                }
            });



            socket.on(game_event_map.READY, (data) => {
                const userId = socket.userId;
                if(userId == null){
                    return;
                }
                socket.gameMgr.setReady(userId);
                UserMgr.broacastInRoom(game_event_map.USER_READY_PUSH, {
                    userId: userId,
                    ready: true,
                }, userId, true);
            });



            socket.on(game_event_map.HUANPAI, (data) => {
                const log = callPathFun(game_event_map.HUANPAI, true);

                if(socket.userId == null){
                    log('socket.userId == null');
                    return;
                }

                if(data == null){
                    log('data == null');
                    return;
                }

                if(typeof data == 'string'){
                    data = JSON.parse(data);
                }

                const p1 = data.p1;
                const p2 = data.p2;
                const p3 = data.p3;
                if(p1 == null || p2 == null || p3 == null){
                    log('p1 == null || p2 == null || p3 == null');
                    return;
                }

                socket.gameMgr.huanSanZhang(socket.userId, p1, p2, p3);
            });



            socket.on(game_event_map.DINGQUE, (data) => {
                if(socket.userId == null){
                    return;
                }
                const que = data;
                socket.gameMgr.dingQue(socket.userId, que);
            });



            socket.on(game_event_map.CHUPAI, (data) => {
                if(socket.userId == null){
                    return;
                }
                const pai = data;
                socket.gameMgr.chuPai(socket.userId, pai);
            });



            socket.on(game_event_map.PENG, (data) => {
                if(socket.userId == null){
                    return;
                }
                socket.gameMgr.peng(socket.userId);
            });



            socket.on(game_event_map.GANG, (data) => {
                const log = callPathFun(game_event_map.GANG);

                if(socket.userId == null || data == null){
                    return;
                }

                let pai = -1;
                if(typeof data == 'number'){
                    pai = data;
                }
                else if(typeof data == 'string'){
                    pai = parseInt(data);
                }
                else{
                    log('参数类型不对');
                    return;
                }
                socket.gameMgr.gang(socket.userId, pai);
            });




            socket.on(game_event_map.HU, (data) => {
                if(socket.userId == null){
                    return;
                }

                socket.gameMgr.hu(socket.userId);
            });



            socket.on(game_event_map.GUO, (data) => {
                if(socket.userId == null){
                    return;
                }
                socket.gameMgr.guo(socket.userId);
            });



            socket.on(game_event_map.CHAT, (data) => {
                if(socket.userId == null){
                    return;
                }
                UserMgr.broacastInRoom(game_event_map.CHAT_PUSH, {sender: socket.userId, content: data}, socket.userId, true);
            });



            socket.on(game_event_map.QUICK_CHAT, (data) => {
                if (socket.userId == null) {
                    return;
                }
                UserMgr.broacastInRoom(game_event_map.QUICK_CHAT_PUSH, {sender: socket.userId, content: data}, socket.userId, true);
            });



            socket.on(game_event_map.VOICE_MSG, (data) => {
                if (socket.userId == null) {
                    return;
                }
                UserMgr.broacastInRoom(game_event_map.VOICE_MSG_PUSH, {sender: socket.userId, content: data}, socket.userId, true);
            });



            socket.on(game_event_map.EMOJI, (data) => {
                if (socket.userId == null) {
                    return;
                }
                UserMgr.broacastInRoom(game_event_map.EMOJI_PUSH, {sender: socket.userId, content: data}, socket.userId, true);
            });



            socket.on(game_event_map.EXIT, (data) => {
                const userId = socket.userId;
                if(userId == null){
                    return;
                }

                const roomId = Roommgr.getUserRoom(userId);
                if(roomId == null){
                    return;
                }

                // 如果游戏已经开始则不可以
                if(socket.gameMgr.hasBegan(roomId)){
                    return;
                }

                // 如果是房主，则只能走解散房间
                if(Roommgr.isCreator(roomId, userId)){
                    return;
                }

                // 通知其他玩家有人退出房间
                UserMgr.broacastInRoom(game_event_map.EXIT_NOTIFY_PUSH, userId, userId, true);

                Roommgr.exitRoom(userId);
                UserMgr.del(userId);

                socket.emit(game_event_map.EXIT_RESULT);
                socket.disconnect();
            });



            socket.on(game_event_map.DISPRESS, (data) => {
                const userId = socket.userId;
                if (userId == null) {
                    return;
                }

                const roomId = Roommgr.getUserRoom(userId);
                if (roomId == null) {
                    return;
                }

                // 如果游戏已经开始则不可以
                if (socket.gameMgr.hasBegan(roomId)) {
                    return;
                }

                // 如果不是房主，则不能解散房间
                if (Roommgr.isCreator(roomId, userId) == false) {
                    return;
                }

                UserMgr.broacastInRoom(game_event_map.DISPRESS_PUSH, {}, userId, true);
                UserMgr.kickAllInRoom(roomId);
                Roommgr.destroy(roomId);
                socket.disconnect();
            });

            socket.on(game_event_map.DISSOLVE_REQUEST, (data) => {
                const userId = socket.userId;
                if (userId == null) {
                    return;
                }

                const roomId = Roommgr.getUserRoom(userId);
                if (roomId == null) {
                    return;
                }

                // 如果游戏没有开始则不可以
                if (socket.gameMgr.hasBegan(roomId) == false) {
                    return;
                }

                const ret = socket.gameMgr.dissolveRequest(roomId, userId);
                if(ret){
                    const dr = ret.dr;
                    const ramaingTime = (dr.endTime - Date.now()) / 1000;
                    const data = {
                        time: ramaingTime,
                        states: dr.states,
                    };
                    UserMgr.broacastInRoom(game_event_map.DISSOLVE_NOTICE_PUSH, data, userId, true);
                }
            });



            socket.on(game_event_map.DISSOLVE_AGREE, (data) => {
                const userId = socket.userId;
                if (userId == null) {
                    return;
                }

                const roomId = Roommgr.getUserRoom(userId);
                if (roomId == null) {
                    return;
                }

                const ret = socket.gameMgr.dissolveAgree(roomId, userId, true);
                if(ret){
                    const dr = ret.dr;
                    const ramaingTime = (dr.endTime - Date.now()) / 1000;
                    const data = {
                        time: ramaingTime,
                        states: dr.states,
                    };
                    UserMgr.broacastInRoom(game_event_map.DISSOLVE_NOTICE_PUSH, data, userId, true);

                    let doAllAgree = true;
                    for(let i = 0; i < dr.states.length; i++){
                        if(dr.states[i] == false){
                            doAllAgree = false;
                            break;
                        }
                    }
                    // 所有人都同意了
                    if(doAllAgree){
                        socket.gameMgr.doDisslove(roomId);
                    }
                }
            });



            socket.on(game_event_map.DISSOLVE_REJECT, (data) => {
                const userId = socket.userId;
                if (userId == null) {
                    return;
                }

                const roomId = Roommgr.getUserRoom(userId);
                if (roomId == null) {
                    return;
                }

                const ret = socket.gameMgr.dissolveAgree(roomId, userId, false);
                if(ret) {
                    UserMgr.broacastInRoom(game_event_map.DISSOLVE_CANCEL_PUSH, {}, userId, true);
                }
            });




            socket.on(game_event_map.DISCONNECT, (data) => {
                const userId = socket.userId;
                if(userId == null){
                    return;
                }

                // 如果是旧连接断开，则不需要处理
                if(UserMgr.get(userId) != socket){
                    return;
                }

                const sendData = {
                    userId: userId,
                    online: false
                };

                // 通知房间内其他玩家
                UserMgr.broacastInRoom(game_event_map.USER_STATE_PUSH, sendData, userId);
                // 清除玩家的在线信息
                UserMgr.del(userId);
                socket.userId = null;
            });



            socket.on(game_event_map.GAME_PING, () => {
                const userId = socket.userId;
                if (userId == null) {
                    return;
                }

                socket.emit(game_event_map.GAME_PONG);
            });


        });
    }
}